How can I detect if a browser is blocking a popup?
Asked Answered
M

9

165

Occasionally, I've come across a webpage that tries to pop open a new window (for user input, or something important), but the popup blocker prevents this from happening.

What methods can the calling window use to make sure the new window launched properly?

Malformation answered 5/8, 2008 at 22:1 Comment(0)
H
207

If you use JavaScript to open the popup, you can use something like this:

var newWin = window.open(url);             

if(!newWin || newWin.closed || typeof newWin.closed=='undefined') 
{ 
    //POPUP BLOCKED
}
Haileyhailfellowwellmet answered 5/8, 2008 at 22:3 Comment(4)
Here's an answer for chrome: detect-blocked-popup-in-chromeCanto
@Canto could you kindly clarify if this answer fails for chrome, or is there a reason the other answer is better for chrome? thanks!Shrine
@Canto at least today this code seems to work on chrome, hence the question.Shrine
@Shrine - You're asking me about something I answered this 6 years ago - I sadly no longer recall the situation and browsers have come a long ways in 6 years.Canto
K
55

I tried a number of the examples above, but I could not get them to work with Chrome. This simple approach seems to work with Chrome 39, Firefox 34, Safari 5.1.7, and IE 11. Here is the snippet of code from our JS library.

openPopUp: function(urlToOpen) {
    var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");            
    try {
        popup_window.focus();   
    } catch (e) {
        alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
    }
}
Kurtzman answered 31/12, 2014 at 19:16 Comment(3)
@Surendra please, can you specify what you mean with "not working"? An error at parse time? An error at runtime? The popup opens but it is marked as blocked? The popup is blocked but it is marked as open? I don't see any reason why explorer would fail this, unless calling focus() on NULL is allowed in which case, a test for NULL before the try would just work.Metalinguistic
IE always returns null, even if the popup was successful.Bonded
Needed that for Safari in 2024. It's still working.Golly
E
36

Update: Popups exist from really ancient times. The initial idea was to show another content without closing the main window. As of now, there are other ways to do that: JavaScript is able to send requests for server, so popups are rarely used. But sometimes they are still handy.

In the past evil sites abused popups a lot. A bad page could open tons of popup windows with ads. So now most browsers try to block popups and protect the user.

Most browsers block popups if they are called outside of user-triggered event handlers like onclick.

If you think about it, that’s a bit tricky. If the code is directly in an onclick handler, then that’s easy. But what is the popup opens in setTimeout?

Try this code:

 // open after 3 seconds
setTimeout(() => window.open('http://google.com'), 3000);

The popup opens in Chrome, but gets blocked in Firefox.

…And this works in Firefox too:

 // open after 1 seconds
setTimeout(() => window.open('http://google.com'), 1000);

The difference is that Firefox treats a timeout of 2000ms or less are acceptable, but after it – removes the “trust”, assuming that now it’s “outside of the user action”. So the first one is blocked, and the second one is not.


Original answer which was current 2012:

This solution for popup blocker checking has been tested in FF (v11), Safari (v6), Chrome (v23.0.127.95) & IE (v7 & v9). Update the displayError function to handle the error message as you see fit.

var popupBlockerChecker = {
    check: function(popup_window){
        var scope = this;
        if (popup_window) {
            if(/chrome/.test(navigator.userAgent.toLowerCase())){
                setTimeout(function () {
                    scope.is_popup_blocked(scope, popup_window);
                },200);
            }else{
                popup_window.onload = function () {
                    scope.is_popup_blocked(scope, popup_window);
                };
            }
        } else {
            scope.displayError();
        }
    },
    is_popup_blocked: function(scope, popup_window){
        if ((popup_window.innerHeight > 0)==false){ 
            scope.displayError();
        }
    },
    displayError: function(){
       alert("Popup Blocker is enabled! Please add this site to your exception list.");
    }
};

Usage:

var popup = window.open("http://www.google.ca", '_blank');
popupBlockerChecker.check(popup);

Hope this helps! :)

Erst answered 30/11, 2012 at 20:39 Comment(5)
I think you need more underscoresDarfur
In firefox, this displays the blank page and you can't even see the popup blocker message on the opener page. How to close the blank page?Modulus
Note that if popup url is a downloadable file(which has Content-Disposition: attachment; in the response header), the popup will close immediately, therefore setTimeout code will fail, and the browser will complain that "Popup Blocker is enabled!". For Chrome, I recommend @DanielB's solution and it works great.Potaufeu
@Potaufeu when opening a link that has a Content-Disposition: attachment; header you don't need to open it in a popup. Simply make a direct link to the asset your wanting to download and the native behaviour of the browser will allow you to download without redirecting you away from the current page.Erst
@KevinB I have to say that I'm in a specific situation. I have to download multiple files which are generating PDF files from HTML. And if the HTML contents are large, sometimes it takes several seconds and if I use window.location for it, if the first file takes too long to generate, it will be ignored when the second request started. That's the reason why I have to use window.open, since window.location never lets me know when the response finishes.Potaufeu
F
18

One "solution" that will always work regardless of browser company or version is to simply put a warning message on the screen, somewhere close to the control that will create a pop-up, that politely warns the user that the action requires a pop-up and to please enable them for the site.

I know it's not fancy or anything, but it can't get any simpler and only requires about 5 minutes testing, then you can move on to other nightmares.

Once the user has allowed pop-ups for your site, it would also be considerate if you don't overdo the pop-ups. The last thing you want to do is annoy your visitors.

Faludi answered 26/2, 2016 at 22:49 Comment(2)
Unfortunately, sometimes all other solutions in this question are not acceptable - only this one. Why? Because they all try to display a popup - not just detect if popups are enabled. What if I want to do it silently?Victorie
Something to remember here as well is that a user cannot always just enable popups for your site. In older versions of safari for example, a user can only enable or disable the popup blocker completely, no whitelisting available.Tatum
B
1

I've tried lots of solutions, but the only one I could come up with that also worked with uBlock Origin, was by utilising a timeout to check the closed status of the popup.

function popup (url, width, height) {
    const left = (window.screen.width / 2) - (width / 2)
    const top = (window.screen.height / 2) - (height / 2)
    let opener = window.open(url, '', `menubar=no, toolbar=no, status=no, resizable=yes, scrollbars=yes, width=${width},height=${height},top=${top},left=${left}`)

    window.setTimeout(() => {
        if (!opener || opener.closed || typeof opener.closed === 'undefined') {
            console.log('Not allowed...') // Do something here.
        }
    }, 1000)
}

Obviously this is a hack; like all solutions to this problem.

You need to provide enough time in your setTimeout to account for the initial opening and closing, so it's never going to be thoroughly accurate. It will be a position of trial and error.

Add this to your list of attempts.

Bogtrotter answered 30/1, 2018 at 12:29 Comment(0)
P
1

I combined @Kevin B and @DanielB's solutions.
This is much simpler.

var isPopupBlockerActivated = function(popupWindow) {
    if (popupWindow) {
        if (/chrome/.test(navigator.userAgent.toLowerCase())) {
            try {
                popupWindow.focus();
            } catch (e) {
                return true;
            }
        } else {
            popupWindow.onload = function() {
                return (popupWindow.innerHeight > 0) === false;
            };
        }
    } else {
        return true;
    }
    return false;
};

Usage:

var popup = window.open('https://www.google.com', '_blank');
if (isPopupBlockerActivated(popup)) {
    // Do what you want.
}
Potaufeu answered 27/2, 2019 at 5:53 Comment(1)
isPopupBlockerActivated function never returns on return (popupWindow.innerHeight > 0) === false;. You function returns false when your browser is not Chrome. Because onload is asynchronous process. Your function returns false and then onload executed but its result never returns.Linchpin
H
1

A simple approach if you own the child code as well, would be to create a simple variable in its html as below:

    <script>
        var magicNumber = 49;
    </script>

And then check its existence from parent something similar to following:

    // Create the window with login URL.
    let openedWindow = window.open(URL_HERE);

    // Check this magic number after some time, if it exists then your window exists
    setTimeout(() => {
        if (openedWindow["magicNumber"] !== 32) {
            console.error("Window open was blocked");
        }
    }, 1500);

We wait for some time to make sure that webpage has been loaded, and check its existence. Obviously, if the window did not load after 1500ms then the variable would still be undefined.

Heavenly answered 31/1, 2020 at 6:52 Comment(2)
how about putting this on window on load handler.Meaghan
@Meaghan We can't because the check is happening on parent window, whereas the magicNumber variable resides on child window.Heavenly
S
-1

By using onbeforeunload event we can check as follows

    function popup()
    {
        var chk=false;
        var win1=window.open();
        win1.onbeforeunload=()=>{
            var win2=window.open();
            win2.onbeforeunload=()=>{
                chk=true;
            };
        win2.close();
        };
        win1.close();
        return chk;
    }

it will open 2 black windows in background

the function returns boolean value.

Shammy answered 29/5, 2018 at 14:56 Comment(0)
D
-1

For some popup blockers this don't work but i use it as basic solution and add try {} catch

try {
        const newWindow = window.open(url, '_blank');
        if (!newWindow || newWindow.closed || typeof newWindow.closed == 'undefined')         {
            return null;
        }

        (newWindow as Window).window.focus();
        newWindow.addEventListener('load', function () {
            console.info('Please allow popups for this website')
        })
        return newWindow;
    } catch (e) {
        return null;
    }

This will try to call addEventListaner function but if popup is not open then it will break and go to catch, then ask if its object or null and run rest of code.

Designedly answered 16/9, 2022 at 12:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.